
#ifndef CLIENTE_H_
#define CLIENTE_H_
#include <iostream>
#include <string>
#include <stdio.h>
#include <utility>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <fstream>
#include "../SocketsAndThreads/socket.h"
#include "../SocketsAndThreads/thread.h"
#include "../Utils/Decoder.h"
#include "../Utils/index.h"
#include "../Utils/hmac.h"
#include "ClientPolling.h"
#include "../messages/register.h"

#define MAX_BYTES 1000
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/SimpleLayout.hh>
extern log4cpp::Category& category;

struct to_process{
	Message *msg_;
	int id_;
};

class Cliente : public Thread{
public:

	/*Constructor*/
	Cliente();

	/*Constructor:
	 * s: socket por el cual esta conectado al server
	 * storage_path: path del repositorio
	 * index_path: path de donde esta almacenado el indice de archivos del repositorio
	 * login_path: ubicacion archivo de login
	 * polling_interval: tiempo de intervalo de polling
	 */
	Cliente(Socket* un_socket,std::string& storage_path, std::string& index_path,std::string& login_path, int polling_interval);

	/* Inicializacion de atributos del cliente */
    void initialize(Socket* un_socket,std::string& storage_path, std::string& index_path,std::string& login_path, int polling_interval,std::string user, std::string pass);

    /* Setea socket */
    void setSocket(Socket* un_socket);

    /*Procesa el mensaje recibido por el server*/
    void process_msg(Message* msg, int id);

    /*Procesa el msj recibido por el server*/
	void process(Message *msg, int id);

	/* Devuelve nombre de usuario*/
	std::string getUser();

	/* Devuelve contraseña de usuario */
	std::string getPass();

	/* Setea nombre de usuario y contraseña */
	void setUserPass(std::string& user, std::string& pass);

	/* LLamada por run, escuchando al server*/
	void listen_server();

	/* Procesar resultado de logueo enviado por el server*/
	void process_logging(int id, bool *logging_error, bool *not_max_tries);

	/* Envia la info para loguerse en el server */
	void register_to_server(std::string& user, std::string& pass);

	/* Le pide la lista de archivos al server */
	void get_list_files();

	/* Recibe la lista de archivos del server y les pide los cambios*/
	void recv_list_files(FilesList* list);

	/* Se le pide al server, luego de recibir la lista de archivos enviada por el server*/
	void get_file(std::string& name_file);

	/* Enviado desde metodo polling al server, ya que se encontro una modificacion */
	void put_file(std::string& name_file);

	/*Actualiza los indices y hashes*/
	void update_state(PutFile *d);

	/* Borra archivo de la tabla inWait, utilizada cuando el envio fue exitoso*/
	void delete_in_wait(std::string& name_file);

	/*Borrar del map de archivos a enviar*/
	void delete_in_tosend(std::string& name_file);

	/*Borra el archivo del mapa interno, y el archivo fisico*/
	void delete_file(std::string& name_file);

	/* Devuelve si el cliente esta o no conectado a un servidor */
	bool is_connected();

	/*Thread para escuchar al server*/
	void run();

	/* Destructor*/
	virtual ~Cliente();


private:
	Socket *sock;
    Mutex* m;
	ClientPolling *poller;
	std::string storage_path;
	std::string index_path;
	std::string login_path;
	std::string user;
	std::string pass;
	Index indice;
	std::vector<std::string> inWait; // En espera de ser recibidos
	Index to_send; // archivos que se mandaron a enviar, estaran aca hasta que se reciba putok o no existan mas( esto ultimo ver en la etapa de polling)
	bool connected;
};

#endif /* CLIENTE_H_ */
